package ac.il.technion.cs236635.project.core.policy;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;

import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.name.Names;

public class PolicyConfigurator extends AbstractModule {

	private final static Logger log  = Logger.getLogger( PolicyConfigurator.class);
	
	public static enum PolicyTypes {
		ACCEPT_ALL( "ACCEPT_ALL") {
			@Override
			public void bind(Binder binder) {
				log.debug( "Applying accept all policy configuration");
				binder.bind( AcceptancePolicy.class).annotatedWith( Names.named( "policy")).to( AcceptAllPolicy.class);				
			}
		},
		LIMITTED_BUFFER( "LIMMITED_BUFFER") {
			@Override
			public void bind(Binder binder) {
				int size = getQueueSize( );
				log.debug( "Applying limitted buffer policy configuration. Queue size : " + size);
				binder.bind( AcceptancePolicy.class)
					.annotatedWith( Names.named( "policy"))
					.toInstance( new LimittedBufferPolicy( size));
			}
		},
		LIMITTED_REDIRECT( "LIMITTED_REDIRECT") {
			@Override
			public void bind(Binder binder) {
				int size = getQueueSize( );
				log.debug( "Applying limitted buffer with rederect to another server accept policy configuration. Queue size : " + size);
				binder.bind( AcceptancePolicy.class)
					.annotatedWith( Names.named( "policy"))
					.toInstance( new LimittedBufferRedirectPolicy( size));
			}
		};
		
		private String type;
		
		private static Map< String, PolicyTypes> map = new HashMap< String, PolicyTypes>( ); 
		
		static {
			for ( PolicyTypes $ : PolicyTypes.values( )) {
				map.put( $.type, $);
			}
		}

		public static PolicyTypes fromString( final String type) {
			PolicyTypes result = map.get( type);
			if ( result == null)
				return ACCEPT_ALL;
			return result;
		}
		
		private PolicyTypes( final String type) {
			this.type = type;
		}

		protected int getQueueSize( ) {
			int size = 10;
			Properties properties = new Properties( );
			try {
				properties.load( PolicyTypes.class.getClassLoader().getResourceAsStream( "server.properties"));
				size = Integer.valueOf( properties.getProperty( "queueSize", "10"));
			} catch (IOException e) {
				e.printStackTrace();
			}
			return size;
		}

		
		abstract public void bind( final Binder binder);
	}
	
	@Override
	protected void configure() {
		Properties properties = new Properties( );
		String policy = "ACCEPT_ALL";
		try {
			properties.load ( PolicyConfigurator.class.getClassLoader( ).getResourceAsStream( "server.properties"));
			policy = properties.getProperty( "policy");
		} catch (IOException e) {
			e.printStackTrace();
		}
		PolicyTypes.fromString( policy).bind( binder( ));
	}

}
